/**
 * @file STL_TcpClientMgr.h
 * @author Derek Liu (yjkhtddx@sina.com)
 * @brief 
 * @version 0.1
 * @date 2021-02-08
 * 
 * @copyright Copyright Sci-Tech Laboratories (c) 2021
 * 
 */

#ifndef __STL_TCP_CLIENT_MGR_H__
#define __STL_TCP_CLIENT_MGR_H__

#include <string>
#include <stdint.h>
#include <functional>
#include <thread>
#include <mutex>
#include <list>
#include <queue>
#include <memory>
#include <map>
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include "STL_Tools.h"
#include <string>

#define STL_TcpClientMgr_Buffer_Max 32 * 1024

namespace STL
{
    class STL_TcpClientMgr
    {
    public:
        typedef struct SocketInfo_t
        {
            int socket;
            std::string ip;
            uint16_t port;
            // std::mutex mutex;
            // std::string data;
            SocketInfo_t(int socket, std::string ip, uint16_t port)
            {
                this->socket = socket;
                this->ip = ip;
                this->port = port;
            }
        } SocketInfo;

        typedef std::function<void(int /* socket*/, std::string /*ip*/, uint16_t /*port*/)> ConnectCallback;
        typedef std::function<void(int /* socket*/)> DisconnectCallback;
        typedef std::function<void(int /* socket*/, std::shared_ptr<std::string>)> DataCallback;

    public:// 允许非单例使用
        STL_TcpClientMgr();
        ~STL_TcpClientMgr();

    public:
        static STL_TcpClientMgr *getInstance()
        {
            static STL_TcpClientMgr instance;
            return &instance;
        };

    public:
        int createTcpConnect(std::string ip, uint16_t port);
        int closeTcpConnect(int socket);
        //发送数据（传引用 call by Reference）
        int sendDataReference(int socket, std::string &data);
        int sendData(int socket, std::string data)
        {
            return sendDataReference(socket, data);
        };
        int sendData(int socket, std::string *data)
        {
            return sendDataReference(socket, (*data));
        };

    public:
        STL_SYNTHESIZE(STL::STL_TcpClientMgr::ConnectCallback, m_ConnectCallback, ConnectCallback);
        STL_SYNTHESIZE(STL::STL_TcpClientMgr::DisconnectCallback, m_DisconnectCallback, DisconnectCallback);
        STL_SYNTHESIZE(STL::STL_TcpClientMgr::DataCallback, m_DataCallback, DataCallback);

    public: //event
        int onData(int socket);
        void onConnect(int socket, std::string ip, uint16_t port);
        void onDisconnect(int socket);

    private:
        int m_epoll_fd;

    private:
        bool m_run;
        std::thread m_thread;
        std::mutex m_mutex;
        void tcpThread();

    private:
        std::mutex m_socketMapMutex;
        std::map<int /*fd*/, std::shared_ptr<SocketInfo> /*socketinfo*/> m_socketMap;

    private:
        char *m_buffer[STL_TcpClientMgr_Buffer_Max]; //大内存块放到类里，防止频繁开辟空间
    };
} // namespace STL

#endif //__STL_TCP_CLIENT_MGR_H__